package com.haohan.cloud.scm.saleb.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.haohan.cloud.scm.api.bill.dto.BillInfoDTO;
import com.haohan.cloud.scm.api.bill.entity.ReceivableBill;
import com.haohan.cloud.scm.api.bill.feign.ReceivableBillFeignService;
import com.haohan.cloud.scm.api.bill.req.BillInfoFeignReq;
import com.haohan.cloud.scm.api.constant.ScmCacheNameConstant;
import com.haohan.cloud.scm.api.constant.enums.bill.OrderTypeEnum;
import com.haohan.cloud.scm.api.constant.enums.saleb.BillTypeEnum;
import com.haohan.cloud.scm.api.crm.feign.CustomerDynamicStateFeignService;
import com.haohan.cloud.scm.api.crm.req.CustomerDynamicStateReq;
import com.haohan.cloud.scm.api.goods.dto.GoodsModelDTO;
import com.haohan.cloud.scm.api.goods.feign.GoodsModelFeignService;
import com.haohan.cloud.scm.api.goods.req.GoodsModelFeignReq;
import com.haohan.cloud.scm.api.goods.vo.GoodsModelVO;
import com.haohan.cloud.scm.api.manage.dto.ShopExtDTO;
import com.haohan.cloud.scm.api.manage.entity.Merchant;
import com.haohan.cloud.scm.api.manage.entity.UPassport;
import com.haohan.cloud.scm.api.manage.feign.MerchantFeignService;
import com.haohan.cloud.scm.api.manage.feign.ShopFeignService;
import com.haohan.cloud.scm.api.manage.feign.UPassportFeignService;
import com.haohan.cloud.scm.api.manage.req.MerchantReq;
import com.haohan.cloud.scm.api.manage.req.UPassportReq;
import com.haohan.cloud.scm.api.opc.entity.ShipRecord;
import com.haohan.cloud.scm.api.opc.feign.ShipRecordFeignService;
import com.haohan.cloud.scm.api.opc.req.ship.ShipRecordFeignReq;
import com.haohan.cloud.scm.api.product.entity.SortingOrder;
import com.haohan.cloud.scm.api.product.entity.SortingOrderDetail;
import com.haohan.cloud.scm.api.product.feign.ProductInfoFeignService;
import com.haohan.cloud.scm.api.product.feign.SortingOrderDetailFeignService;
import com.haohan.cloud.scm.api.product.req.CreateSortingOrderReq;
import com.haohan.cloud.scm.api.sys.admin.feign.SysDeptFeignService;
import com.haohan.cloud.scm.api.sys.admin.feign.SysTenantFeignService;
import com.haohan.cloud.scm.api.sys.admin.feign.SystemUserFeignService;
import com.haohan.cloud.scm.api.wms.entity.ExitWarehouseDetail;
import com.haohan.cloud.scm.api.wms.feign.ExitWarehouseDetailFeignService;
import com.haohan.cloud.scm.common.tools.exception.EmptyDataException;
import com.haohan.cloud.scm.common.tools.exception.ErrorDataException;
import com.haohan.cloud.scm.common.tools.util.RUtil;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysDept;
import com.pig4cloud.pigx.admin.api.entity.SysTenant;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.AllArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author cx
 * @date 2019/6/13
 */
@Component
@AllArgsConstructor
public class ScmSaleBUtils {

    private final ProductInfoFeignService productInfoFeignService;
    private final UPassportFeignService uPassportFeignService;
    private final GoodsModelFeignService goodsModelFeignService;
    private final ExitWarehouseDetailFeignService exitWarehouseDetailFeignService;
    private final SortingOrderDetailFeignService sortingOrderDetailFeignService;
    private final SystemUserFeignService systemUserFeignService;
    private final ShopFeignService shopFeignService;
    private final MerchantFeignService merchantFeignService;
    private final ReceivableBillFeignService receivableBillFeignService;
    private final SysTenantFeignService sysTenantFeignService;
    private final SysDeptFeignService sysDeptFeignService;
    private final ShipRecordFeignService shipRecordFeignService;
    private final CustomerDynamicStateFeignService customerDynamicStateFeignService;

    /**
     * 查询全部有效租户
     *
     * @return
     */
    public List<Integer> findTenantIdList() {
        R<List<SysTenant>> resp = sysTenantFeignService.normalList(SecurityConstants.FROM_IN);
        if (!RUtil.isSuccess(resp) || null == resp.getData()) {
            throw new ErrorDataException("找不到有效租户");
        }
        return resp.getData().stream()
                .map(SysTenant::getId)
                .collect(Collectors.toList());
    }

    public SysDept fetchDeptById(String deptId) {
        if (StrUtil.isEmpty(deptId)) {
            return null;
        }
        R<SysDept> r = sysDeptFeignService.getById(deptId, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("查询部门失败");
        }
        return r.getData();
    }

    /**
     * 查询 用户
     *
     * @return 可为null
     */
    public UserInfo fetchUserById(String id) {
        if (StrUtil.isEmpty(id)) {
            return null;
        }
        R<UserInfo> resp = systemUserFeignService.infoById(id, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(resp) || null == resp.getData()) {
            throw new ErrorDataException("用户查询失败");
        }
        return resp.getData();
    }

    /**
     * 查询user by telephone
     *
     * @param telephone
     * @return
     */
    public String queryUser(String telephone) {
        R<String> r = systemUserFeignService.queryUserId(telephone, SecurityConstants.FROM_IN);
        if (!RUtil.isSuccess(r) || null == r.getData()) {
            return null;
        }
        return r.getData();
    }

    public void deleteUser(String userId) {
        Integer id;
        try {
            id = NumberUtil.parseInt(userId);
            if (id == 0) {
                id = null;
            }
        } catch (Exception e) {
            id = null;
        }
        if (null != id) {
            UserDTO user = new UserDTO();
            user.setUserId(id);
            systemUserFeignService.deleteUser(user, SecurityConstants.FROM_IN);
        }
    }

    /**
     * 更新用户信息
     * 修改所有信息，修改用户角色
     *
     * @param user id
     * @return
     */
    public Boolean updateUser(UserDTO user) {
        R<Boolean> r = systemUserFeignService.updateUser(user, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("修改用户失败");
        }
        return r.getData();
    }

    public UserDTO addUser(UserDTO user) {
        R<UserDTO> r = systemUserFeignService.addUser(user, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("新增用户失败");
        }
        // 绑定通行证
        UPassport uPassport = new UPassport();
        uPassport.setTelephone(user.getPhone());
        uPassport.setLoginName(user.getUsername());
        uPassport.setPassword(user.getPassword());
        uPassport.setAvatar(user.getAvatar());
        String uid = addUPassPort(uPassport).getId();
        // uid 存入
        r.getData().setOscId(uid);
        return r.getData();
    }

    /**
     * 新增通行证账号, 相同手机号会覆盖以前的
     *
     * @param uPassport
     * @return
     */
    public UPassport addUPassPort(UPassport uPassport) {
        R<UPassport> r = uPassportFeignService.add(uPassport, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("新增通行证账号时失败");
        }
        return r.getData();
    }

    /**
     * 查询upassport by 手机号码
     *
     * @param telephone
     * @return
     */
    public UPassport queryUPassport(String telephone) {
        UPassportReq req = new UPassportReq();
        req.setTelephone(telephone);
        R<UPassport> r = uPassportFeignService.getOneByUPassportReq(req, SecurityConstants.FROM_IN);
        if (!RUtil.isSuccess(r) || null == r.getData()) {
            return new UPassport();
        }
        return BeanUtil.toBean(r.getData(), UPassport.class);
    }

    /**
     * 根据Id查询GoodsModelDTO
     *
     * @param id
     * @return
     */
    public GoodsModelDTO queryGoodsModelById(String id) {
        R<GoodsModelDTO> r = goodsModelFeignService.getInfoById(id, SecurityConstants.FROM_IN);
        if (!RUtil.isSuccess(r) || null == r.getData()) {
            throw new ErrorDataException("查询商品信息失败");
        }
        return r.getData();
    }

    /**
     * 根据id查询商品规格信息  (使用平台定价)
     * 无typeName
     *
     * @param modelId
     * @param buyerId
     * @param pricingDate
     * @return
     */
    public GoodsModelVO queryGoodsModelVO(String modelId, String buyerId, LocalDate pricingDate) {
        GoodsModelFeignReq req = new GoodsModelFeignReq();
        req.setModelId(modelId);
        req.setBuyerId(buyerId);
        req.setPricingDate(pricingDate);
        R<GoodsModelVO> r = goodsModelFeignService.fetchModelVO(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r) || null == r.getData()) {
            throw new ErrorDataException("查询商品规格信息时失败");
        }
        return r.getData();

    }

    /**
     * 创建出库单明细(锁库存)
     *
     * @param detail 实体对象 需创建的出库单信息
     * @return R
     */
    public ExitWarehouseDetail createExitDetailStock(ExitWarehouseDetail detail) {
        R r = exitWarehouseDetailFeignService.createExitDetailStock(detail, SecurityConstants.FROM_IN);
        if (!RUtil.isSuccess(r) || null == r.getData()) {
            throw new EmptyDataException("创建出库单明细(锁库存)有误");
        }
        return BeanUtil.toBean(r.getData(), ExitWarehouseDetail.class);
    }

    /**
     * 新增货品分拣单  根据B客户订单
     *
     * @param req
     * @return
     */
    public SortingOrder createSortingOrder(CreateSortingOrderReq req) {
        R r = productInfoFeignService.createSortingOrder(req, SecurityConstants.FROM_IN);
        if (!RUtil.isSuccess(r) || null == r.getData()) {
            throw new EmptyDataException("新增货品分拣单有误");
        }
        return BeanUtil.toBean(r.getData(), SortingOrder.class);
    }


    /**
     * 修改分拣单明细 根据B订单明细编号
     *
     * @param sortingOrderDetail 必须 pmId/ BuyDetailSn
     */
    public Boolean modifySortingDetailBySn(SortingOrderDetail sortingOrderDetail) {
        R r = sortingOrderDetailFeignService.modifySortingDetailBySn(sortingOrderDetail, SecurityConstants.FROM_IN);
        if (!RUtil.isSuccess(r)) {
            throw new ErrorDataException("修改分拣单明细失败");
        }
        return (Boolean) r.getData();
    }

    /**
     * 名称查询, 若无对应商品则新增 商品(下架状态, 分类为  未确认商品-> 导入商品)
     *
     * @param goodsModelDTO goodsName / modelName /unit /price / shopId
     * @return
     */
    public GoodsModelDTO fetchModelByNameOrAdd(GoodsModelDTO goodsModelDTO) {
        R r = goodsModelFeignService.fetchModelByNameOrAdd(goodsModelDTO, SecurityConstants.FROM_IN);
        if (!RUtil.isSuccess(r)) {
            throw new ErrorDataException("获取商品规格失败");
        }
        return BeanUtil.toBean(r.getData(), GoodsModelDTO.class);
    }

    /**
     * 获取平台商家的采购配送店铺
     *
     * @param pmId
     * @return 失败为null
     */
    public ShopExtDTO fetchPurchaseShop(String pmId) {
        R<ShopExtDTO> r = shopFeignService.fetchPurchaseShop(pmId, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("获取平台商家的采购配送店铺失败");
        }
        return r.getData();
    }

    /**
     * 查询采购商 应收订单数
     *
     * @param req
     * @return 失败时返回0；
     */
    public Integer countReceivableBill(BillInfoFeignReq req) {
        R<BillInfoDTO> r = receivableBillFeignService.countBill(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r) || null == r.getData()) {
            return 0;
        }
        return r.getData().getTotal().intValue();
    }

    /**
     * 根据商家名称查询
     *
     * @param merchantName
     * @return
     */
    public Merchant fetchMerchantByName(String merchantName) {
        if (StrUtil.isEmpty(merchantName)) {
            return null;
        }
        MerchantReq merchantReq = new MerchantReq();
        merchantReq.setMerchantName(merchantName);
        R<Merchant> r = merchantFeignService.getOneByMerchantReq(merchantReq, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("商家查询失败");
        }
        return r.getData();
    }

    public Merchant fetchMerchantById(String merchantId) {
        R<Merchant> r = merchantFeignService.getById(merchantId, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("查询商家时失败");
        }
        return r.getData();
    }

    /**
     * 创建平台的商家
     *
     * @param merchant
     * @return
     */
    public Merchant createMerchantWithPlatform(Merchant merchant) {
        R<Merchant> r = merchantFeignService.createMerchantWithPlatform(merchant, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("商家创建失败");
        }
        return r.getData();
    }

    /**
     * 查询租户的平台商家
     *
     * @return
     */
    @Cacheable(value = ScmCacheNameConstant.MANAGE_PLATFORM_MERCHANT, key = "0")
    public Merchant fetchPlatformMerchant() {
        R<Merchant> r = merchantFeignService.fetchPlatformMerchant(SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("查询租户的平台商家失败");
        } else if (null == r.getData()) {
            throw new ErrorDataException("查询平台商家失败");
        }
        return r.getData();
    }

    /**
     * 批量创建账单 (订单应收)
     *
     * @param orderSnSet
     */
    public boolean createBillBatch(Set<String> orderSnSet) {
        BillInfoFeignReq req = new BillInfoFeignReq();
        req.setOrderSnSet(orderSnSet);
        req.setBillType(BillTypeEnum.order);
        R<Boolean> r = receivableBillFeignService.createNormalBillBatch(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r) || null == r.getData()) {
            return false;
        }
        return r.getData();
    }

    /**
     * 创建账单 (订单应收)
     *
     * @param orderSn
     */
    public BillInfoDTO createBill(String orderSn) {
        BillInfoDTO req = new BillInfoDTO();
        req.setOrderSn(orderSn);
        req.setBillType(BillTypeEnum.order);
        req.setAdvanceAmount(BigDecimal.ZERO);
        R<BillInfoDTO> r = receivableBillFeignService.createBill(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r) || null == r.getData()) {
            throw new ErrorDataException("创建账单时失败:" + r.getMsg());
        }
        return r.getData();
    }

    /**
     * 删除账单 不为已审核通过
     *
     * @param buyOrderSn
     * @param type
     * @return
     */
    public boolean deleteBillByOrder(String buyOrderSn, BillTypeEnum type) {
        BillInfoFeignReq req = new BillInfoFeignReq();
        req.setOrderSn(buyOrderSn);
        req.setBillType(type);
        R<Boolean> r = receivableBillFeignService.deleteBillByOrder(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("删除账单时失败:" + r.getMsg());
        }
        return r.getData();
    }

    /**
     * 根据订单信息更新账单(普通账单)
     * 无账单时无操作
     * 账单不能已结算
     *
     * @param buyOrderSn
     * @param type
     * @return
     */
    public void updateBillByOrder(String buyOrderSn, BillTypeEnum type) {
        BillInfoFeignReq req = new BillInfoFeignReq();
        req.setOrderSn(buyOrderSn);
        req.setBillType(type);
        R<Boolean> r = receivableBillFeignService.updateBillByOrder(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("根据订单信息更新账单时失败:" + r.getMsg());
        }
    }

    public ReceivableBill fetchNormalBillByOrder(String buyOrderSn) {
        R<ReceivableBill> r = receivableBillFeignService.fetchNormalByOrder(buyOrderSn, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("根据订单编号查询应收账单时失败:" + r.getMsg());
        }
        return r.getData();
    }

    /**
     * 删除发货记录 (不为已发货)
     *
     * @param buyOrderSn
     * @param type
     * @return
     */
    public boolean deleteShipRecord(String buyOrderSn, OrderTypeEnum type) {
        ShipRecordFeignReq req = new ShipRecordFeignReq();
        req.setOrderSn(buyOrderSn);
        req.setOrderType(type);
        R<Boolean> r = shipRecordFeignService.deleteShipRecordByOrder(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("删除发货记录时失败");
        }
        return r.getData();
    }

    /**
     * 根据订单信息更新发货记录  (不为已发货)
     *
     * @param buyOrderSn
     * @param type
     * @return
     */
    public boolean updateShipRecord(String buyOrderSn, OrderTypeEnum type) {
        ShipRecordFeignReq req = new ShipRecordFeignReq();
        req.setOrderSn(buyOrderSn);
        req.setOrderType(type);
        R<Boolean> r = shipRecordFeignService.updateShipRecordByOrder(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("根据订单信息更新发货记录时失败");
        }
        return r.getData();
    }

    /**
     * 根据订单创建发货记录(已存在发货记录则修改)
     *
     * @param orderSn
     */
    public void createShipRecord(String orderSn) {
        ShipRecordFeignReq req = new ShipRecordFeignReq();
        req.setOrderSn(orderSn);
        req.setOrderType(OrderTypeEnum.buy);
        R<ShipRecord> r = shipRecordFeignService.createShipRecordByOrder(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("根据订单创建发货记录时失败:" + r.getMsg());
        }
    }

    /**
     * 根据订单创建发货记录(批量)
     *
     * @param orderSnSet
     * @return
     */
    public boolean createShipRecordBatch(Set<String> orderSnSet) {
        ShipRecordFeignReq req = new ShipRecordFeignReq();
        req.setOrderSnSet(orderSnSet);
        req.setOrderType(OrderTypeEnum.buy);
        R<Boolean> r = shipRecordFeignService.createShipRecordBatchByOrder(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r) || null == r.getData()) {
            return false;
        }
        return r.getData();
    }

    public ShipRecord fetchShipRecord(String salesOrderSn) {
        ShipRecordFeignReq req = new ShipRecordFeignReq();
        req.setOrderSn(salesOrderSn);
        R<ShipRecord> r = shipRecordFeignService.fetchOneByOrder(req, SecurityConstants.FROM_IN);
        if (RUtil.isFailed(r)) {
            throw new ErrorDataException("查询发货记录时失败:" + r.getMsg());
        }
        return r.getData();
    }

    /**
     * 创建客户采购的动态记录
     *
     * @param req
     * @return
     */
    public boolean createCustomerBuyDynamic(CustomerDynamicStateReq req) {
        try {
            R<Boolean> r = customerDynamicStateFeignService.createCustomerBuyDynamic(req, SecurityConstants.FROM_IN);
            if (RUtil.isFailed(r) || null == r.getData()) {
                return false;
            }
            return r.getData();
        } catch (Exception e) {
            return false;
        }
    }
}
